package gnss

import (
	"dgo/goutils/dnet"
	"dgo/goutils/utils"
	"net/url"
)

func OnReadBuf(connstring string, onBuf func(buf []byte) bool) {
	if ok, str := utils.CheckTrimPrefix(connstring, "ntripclt://"); ok {
		OnNtripClientBuf(str, func(sender *NtripClientUtil, buf []byte) bool {
			return onBuf(buf)
		})
	} else if ok, str := utils.CheckTrimPrefix(connstring, "ntrip://"); ok {
		OnNtripClientBuf(str, func(sender *NtripClientUtil, buf []byte) bool {
			return onBuf(buf)
		})
	} else if ok, str := utils.CheckTrimPrefix(connstring, "tcp://"); ok {
		OnTcpClientBuf(str, func(sender *dnet.ASyncTcpClient, buf []byte) bool {
			return onBuf(buf)
		})
	} else if ok, str := utils.CheckTrimPrefix(connstring, "file://"); ok {
		OnFileBuf(str, onBuf)
	} else if ok, str := utils.CheckTrimPrefix(connstring, "hex://"); ok {
		onBuf(utils.HexStrToBuf(str))
	} else {
		if utils.FileIsExists(connstring) {
			OnFileBuf(str, onBuf)
		} else {
			OnNtripClientBuf(connstring, func(sender *NtripClientUtil, buf []byte) bool {
				return onBuf(buf)
			})
		}
	}
}

func OnNtripClientBuf(connstring string, onBuf func(sender *NtripClientUtil, buf []byte) bool) *NtripClientUtil {
	conf := ParseNtripClientConnectString(connstring)
	rval := &NtripClientUtil{}
	clt := NewNtripClient()
	rval.clt = clt
	if len(conf.Addr) > 0 {
		clt.SetRemoteAddress(conf.Addr)
		clt.SetNtripClientUser(conf.User, conf.Pass)
		clt.SetRequestMountPoint(conf.MountPoint)
		rval.SetNmea(conf.NMEA)
	}
	if len(conf.Conf) > 0 {
		vals, err := url.ParseQuery(conf.Conf)
		if err == nil {
			if vals.Get("rand") == "1" {
				rval.RandPosi = 1
			}
		}
	}

	clt.SetOnRecvBuffer(func(sender *NtripClient, buffer []byte) {
		if !onBuf(rval, buffer) {
			go func() {
				if utils.GoFunCatchException {
					defer utils.PanicHandler()
				}
				clt.Close()
				rval.Close()
			}()
		}
	})
	rval.Open()
	return rval
}

func OnTcpClientBuf(connstring string, onBuf func(sender *dnet.ASyncTcpClient, buf []byte) bool) {
	tcpClt := dnet.NewASyncTcpClient()
	tcpClt.SetAddress(connstring)
	tcpClt.OnRecvBuffer = func(client *dnet.ASyncTcpClient, buffer []byte) {
		if !onBuf(tcpClt, buffer) {
			go func() {
				if utils.GoFunCatchException {
					defer utils.PanicHandler()
				}
				tcpClt.Stop()
			}()
		}
	}
	tcpClt.Start()
}

func OnFileBuf(connstring string, onBuf func(buf []byte) bool) {
	utils.ReadFileBlockBuf(connstring, func(block []byte) bool {
		return onBuf(block)
	}, func() []byte {
		return make([]byte, 8192)
	})
}
